// Package main 演示GORM的一对一关联关系操作
// 本示例展示了如何在GORM中定义、创建、查询和删除具有一对一关联关系的数据
// 具体演示了UserModel和UserDetailModel之间的一对一关联操作
package main

import (
	"fmt"
	"gin-gorm/global"
	"gin-gorm/models"
)

// inerts 演示创建具有一对一关联关系的数据
// 该函数包含两种创建关联数据的方式：
// 1. 通过主表(UserModel)创建并级联创建从表(UserDetailModel)
// 2. 通过从表(UserDetailModel)创建并关联已有主表记录
func inerts() {
	// 创建 用户，连带着 创建 用户详情
	// 这种方式会同时创建UserModel和UserDetailModel两条记录
	// 并自动建立它们之间的关联关系
	// err := global.DB.Create(&models.UserModel{
	// 	Name: "枫枫123",
	// 	Age:  25,
	// 	UserDetailModel: &models.UserDetailModel{
	// 		Email: "枫枫@qq.com",
	// 	},
	// }).Error
	// fmt.Println(err)

	// 创建用户详情, 关联 已有用户
	// 这种方式仅创建UserDetailModel记录
	// 并将其关联到已存在的UserModel记录（通过UserID或UserModel字段）
	err := global.DB.Create(&models.UserDetailModel{
		Email:     "xxx@qq.com",
		UserModel: &models.UserModel{ID: 2}, // 通过嵌套UserModel结构体关联已有用户
		//UserID: 2, // 也可以直接设置外键字段进行关联
	}).Error
	fmt.Println(err)
}

// find 演示查询具有一对一关联关系的数据
// 该函数包含两种查询关联数据的方式：
// 1. 从从表(UserDetailModel)查询并预加载主表(UserModel)数据（正查）
// 2. 从主表(UserModel)查询并预加载从表(UserDetailModel)数据（反查）
func find() {
	// 通过用户详情查用户 正查
	// 从UserDetailModel出发，查询并加载关联的UserModel数据
	var id = 2
	var detail models.UserDetailModel
	// Preload方法用于预加载关联数据，避免N+1查询问题
	// Take方法获取单条记录
	global.DB.Preload("UserModel").Take(&detail, "user_id = ?", id)
	fmt.Println(detail.Email, detail.UserModel.Name) // 输出用户详情的Email和关联用户的Name

	// 反查
	// 从UserModel出发，查询并加载关联的UserDetailModel数据
	var user models.UserModel
	// Preload方法预加载UserDetailModel关联数据
	global.DB.Preload("UserDetailModel").Take(&user, id)
	fmt.Println(user.Name, user.UserDetailModel.Email) // 输出用户的Name和关联详情的Email
}

// delete 演示删除具有一对一关联关系的数据
// 该函数包含两种删除关联数据的策略：
// 1. 级联删除 - 同时删除主表和从表记录
// 2. 设置外键为NULL - 保留从表记录但解除关联
func delete() {
	// // 级联删除
	// // 同时删除UserModel和关联的UserDetailModel记录
	// var user models.UserModel
	// global.DB.Unscoped().Take(&user, 14) // 使用Unscoped()进行物理删除，不使用软删除
	// //global.DB.Unscoped().Delete(&user) // 直接删除用户，不会删除关联的详情
	// global.DB.Unscoped().Select("UserDetailModel").Delete(&user) // 选择删除UserDetailModel关联数据

	// set null - 设置关联字段为null的清理操作
	// 这种方式保留UserDetailModel记录，但将其UserID字段设置为NULL
	var user models.UserModel
	global.DB.Unscoped().Take(&user, 15) // 获取要删除的用户记录
	// Association().Clear() 将关联的外键设置为NULL，但不删除UserDetailModel记录
	global.DB.Model(&user).Association("UserDetailModel").Clear()
	global.DB.Unscoped().Delete(&user) // 物理删除用户记录
}

// main 程序入口函数
// 初始化数据库连接并调用不同的关联操作函数进行演示
func main() {
	// 初始化数据库连接
	global.Connect()
	// inerts() // 调用inerts函数执行关联数据创建操作
	// find() // 调用find函数执行关联数据查询操作
	delete() // 调用delete函数执行关联数据删除操作
}
